/**
*****************************************************************************
 * @file func_DownMode.c
 * @brief 下行设备读取功能函数
 * @author Moon
 * @version V1.0.0
 * @date 2022/09/14
****************************************************************************
 */
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "stack_macros.h" 
 
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "func_DownMode.h"

/* Private defines ---------------------------------------------------------------*/
/* Private Variable ---------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

//Pointer
//Array
//Const

/***********************************************************************************
 * @brief 下行通信接收数据
 * ex:
 * @par 
 * None
 * @retval -1 异常 
 **********************************************************************************/
static void read_callback(func_DownMode_t *this, uint8_t *data, uint32_t len)
{
    if (this == NULL || data == NULL)
        return;

        if (this->private.pNowTask != NULL)
        {
            this->private.waitOut = 0;
            if (this->private.pNowTask->pTaskRecv != NULL)
                this->private.pNowTask->pTaskRecv(this, data, len);
        }

    return;
}

/**
 * 筛选高优先级的任务
 */
static DOWN_COMM_TASK *SelectCommTask(func_DownMode_t *this)
{
    for(uint8_t i=0; i<ComType_NUM; i++)
    {
        if(this->private.taskThread[i].pTaskSend == NULL)
            continue;
        
        return &this->private.taskThread[i];
    }
    return NULL;
}

/***********************************************************************************
 * @brief 下行通信任务轮询
 * ex:
 * @par timebase:执行周期
 * None
 * @retval -1 异常 
 **********************************************************************************/
static void DownMode_task(func_DownMode_t *this, uint16_t timebase)
{
    if (this == NULL || timebase == 0)
        return;

    DOWN_TASK_STATE  taskState;
    uint8_t pBuf[DOWNMODE_NUM];
    FunDownMode_private_t *p_pri = NULL;

    p_pri = &this->private;
    /* 通信通道接收：检测接收超时，若接收超时之前收到数据则处理之，并准备下一次的发送。
     * 若接收超时，则进行重发。若重发次数已经达到最大限制，则反馈通信失败，并开始时下一次的发送。*/
    if (ST_SERIAL_COMM_Recv == p_pri->state)
    {
        if (p_pri->waitOut > 0)
        {
            p_pri->waitOut -= timebase;
            if (p_pri->waitOut <= 0)
            {
                if (p_pri->Cnt > 0)
                {
                    p_pri->Cnt--;
                    p_pri->state = ST_SERIAL_COMM_ReSend;
                }
                else
                {
                    if (p_pri->pNowTask->pTaskRecv != NULL)
                        p_pri->pNowTask->pTaskRecv(this, NULL, 0);    //pTaskRecv绑定read_callback（串口接收idlecallback）
                    
                    if (p_pri->pNowTask->pTaskState == NULL)//如果任务申请时不需要状态管理 执行一次发送后直接结束
                        p_pri->state = ST_SERIAL_COMM_End;
                    else
                        p_pri->state = ST_SERIAL_COMM_Idle;
                }
            }
            else
                return ;
        }
        else
        {
            //此种情况为接收成功数据
            if (p_pri->idleTime > 0)
            {
                p_pri->idleTime -= timebase;
                return ;
            }
            p_pri->Cnt = 0;
            if (p_pri->pNowTask->pTaskState == NULL)//如果任务申请时不需要状态管理 执行一次发送后直接结束
                p_pri->state = ST_SERIAL_COMM_End;
            else
                p_pri->state = ST_SERIAL_COMM_Idle;
        }
    }
    
    /* 通信通道任务结束*/
    if (ST_SERIAL_COMM_End == p_pri->state)
    {
        memset(p_pri->pNowTask, 0, sizeof(DOWN_COMM_TASK));
        p_pri->pNowTask = NULL;
        p_pri->state = ST_SERIAL_COMM_Idle;    //切换到空闲状态继续检测下一个任务
    }
    
    /* 通信通道空闲：检测是否有新的通信任务，选择优先级较高并且可被执行的任务进行通信发送*/
    if (ST_SERIAL_COMM_Idle == p_pri->state)
    {
        p_pri->pNowTask = SelectCommTask(this);
        if (p_pri->pNowTask == NULL) return ;
        
        if (p_pri->pNowTask->pTaskState != NULL)
        {
            taskState = p_pri->pNowTask->pTaskState(this);
            if (taskState == Task_IsWait) return;
            if (taskState == Task_IsOver)
            {
                p_pri->state = ST_SERIAL_COMM_End;
                return;
            }
        }
        
        p_pri->state = ST_SERIAL_COMM_Send;
    }
    
    /* 通信通道发送：调用发送处理函数，按照发送次数、帧延迟、通信参数进行发送；*/
    if ((ST_SERIAL_COMM_Send == p_pri->state) || (ST_SERIAL_COMM_ReSend == p_pri->state))
    {
        if (ST_SERIAL_COMM_Send == p_pri->state)
        {
            if (p_pri->pNowTask->pTaskSend != NULL)
            {
				taskENTER_CRITICAL();
                p_pri->sendLen = p_pri->pNowTask->pTaskSend(this, pBuf);
                p_pri->Cnt = this->SendCnt;
                p_pri->idleTime = this->IdleDelay;
				taskEXIT_CRITICAL();
            }
            else
            {
                p_pri->sendLen = 0;
                p_pri->Cnt = 0;
            }
        }
        else{
			taskENTER_CRITICAL();
            p_pri->sendLen = p_pri->pNowTask->pTaskSend(this, pBuf);
			taskEXIT_CRITICAL();
		}
        
        if (p_pri->sendLen <= 0)
        {
            //if(pCtrl->pNowTask->pTaskRecv != NULL)
            //    pCtrl->pNowTask->pTaskRecv(port, NULL, 0);
            p_pri->waitOut = 0;
        }
        else
        {
            this->send_data(pBuf, p_pri->sendLen);    //串口发送PowCom_send_data
            if (this->outTime == 0)
                p_pri->waitOut = 1000;  //默认1000ms超时时间
            else
                p_pri->waitOut = this->outTime;
        }
        p_pri->state = ST_SERIAL_COMM_Recv;
    }
}

/**
 * 检测同类型的任务是否正在执行或者等待执行
 */
static bool CommTaskIsBusy(func_DownMode_t *this, DOWN_TYPE type)
{
    if(this == NULL) return false;
    if(type >= ComType_NUM) return false;
    
    return DownCommTaskIsBusy(&this->private.taskThread[(uint8_t)type]);
}

/**
 * 取消通信任务
 * 置通道状态函数为空，这样在本次通信结束后
 */
static bool CommTaskCancel(func_DownMode_t *this, DOWN_TYPE type)
{
    bool isIdle = false;
    
    if(this == NULL) return false;
    if(type >= ComType_NUM) return false;
    if(this->private.pNowTask != &this->private.taskThread[(uint8_t)type])
        isIdle = true;
    
    return DownCommTaskCancel(&this->private.taskThread[(uint8_t)type], isIdle);
}

/**
 * 申请通信任务
 */
static bool CommTaskApply(func_DownMode_t *this, DOWN_TYPE type,
                          F_TaskState *pSt, F_TaskSend *pTx, F_TaskRecv *pRx)
{
    if(this == NULL) return false;
    if(type >= ComType_NUM) return false;
    
    return DownCommTaskApply(&this->private.taskThread[(uint8_t)type], pSt, pTx, pRx);
}

/***********************************************************************************
 * @brief 下行通信初始化
 * ex:
 * @par 
 * None
 * @retval -1 异常 
 **********************************************************************************/
int Func_DownMode_Init(func_DownMode_t *this)
{
    if (this == NULL)
        return - 1;

    memset(&this->private, 0, sizeof(FunDownMode_private_t));

    this->read_callback = read_callback;
    this->DownMode_task = DownMode_task;
    
    this->CommTaskIsBusy = CommTaskIsBusy;
    this->CommTaskCancel = CommTaskCancel;
    this->CommTaskApply = CommTaskApply;

    return 0;
}
